home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GameStar 2004 April
/
Gamestar_61_2004-04_dvdb.iso
/
DVDStar
/
Editace
/
hltp.exe
/
{app}
/
Source Code
/
MAP Viewer
/
Engine.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
2003-10-09
|
14KB
|
631 lines
/*
Half-Life MAP viewing utility.
Copyright (C) 2003 Ryan Samuel Gregg
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stdafx.h"
#include "Engine.h"
CEngine::CEngine(CConfig *Config, CRichTextBox *txtConsole)
{
this->Config = Config;
this->txtConsole = txtConsole;
vMouseOld.X = 0;
vMouseOld.Y = 0;
vMouseNew.X = 0;
vMouseNew.Y = 0;
Frustum = new CFrustum();
Camera = new CCamera();
TextureManager = NULL;
World = NULL;
HighlightObject = NULL;
PointFile = NULL;
}
bool CEngine::Initialize(HWND hWND)
{
this->hWND = hWND;
int iPixelFormat;
PIXELFORMATDESCRIPTOR pfd;
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = Config->bColorBits;
pfd.cRedBits = 0;
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0;
pfd.cAlphaShift = 0;
pfd.cAccumBits = 0;
pfd.cAccumRedBits = 0;
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = Config->bDepthBits;
pfd.cStencilBits = 0;
pfd.cAuxBuffers = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.bReserved = 0;
pfd.dwLayerMask =0;
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;
hDC = GetDC(hWND);
if((iPixelFormat = ChoosePixelFormat(hDC, &pfd)) == 0)
return false;
if(SetPixelFormat(hDC, iPixelFormat, &pfd) == false)
return false;
if((hGLRC = wglCreateContext(hDC)) == 0)
return false;
if(wglMakeCurrent(hDC, hGLRC) == false)
return false;
glClearColor(Config->cBackColor.R, Config->cBackColor.G, Config->cBackColor.B, Config->cBackColor.A);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glHint(GL_FOG_HINT, GL_NICEST);
glCullFace(GL_FRONT);
glShadeModel(GL_FLAT);
// Lighting
float fGlobalAmbient[] = { 0.25f, 0.25f, 0.25f, 1.0f };
float fLightAmbient0[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float fLightDiffuse0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float fLightSpecular0[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float fLightPosition0[] = { 4096.0f, 4096.0f, 4096.0f, 0.0f };
float fMaterialSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
float fMaterialEmission[] = { 0.0f, 0.0f, 0.0f, 1.0f };
//glLightModelfv(GL_AMBIENT, fGlobalAmbient);
glLightfv(GL_LIGHT0, GL_AMBIENT, fLightAmbient0);
glLightfv(GL_LIGHT0, GL_DIFFUSE, fLightDiffuse0);
glLightfv(GL_LIGHT0, GL_SPECULAR, fLightSpecular0);
glLightfv(GL_LIGHT0, GL_POSITION, fLightPosition0);
float fLightAmbient1[] = { 0.25f, 0.25f, 0.25f, 1.0f };
float fLightDiffuse1[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float fLightSpecular1[] = { 0.5f, 0.5f, 0.5f, 1.0f };
float fLightPosition1[] = { -4096.0f, -4096.0f, -4096.0f, 0.0f };
glLightfv(GL_LIGHT1, GL_AMBIENT, fLightAmbient1);
glLightfv(GL_LIGHT1, GL_DIFFUSE, fLightDiffuse1);
glLightfv(GL_LIGHT1, GL_SPECULAR, fLightSpecular1);
glLightfv(GL_LIGHT1, GL_POSITION, fLightPosition1);
glMaterialfv(GL_BACK, GL_SPECULAR, fMaterialSpecular);
glMaterialfv(GL_BACK, GL_EMISSION, fMaterialEmission);
// Fog
switch(Config->eFogMode)
{
case FogMode::Exp:
glFogi(GL_FOG_MODE, GL_EXP);
break;
case FogMode::Exp2:
glFogi(GL_FOG_MODE, GL_EXP2);
break;
case FogMode::Linear:
default:
glFogi(GL_FOG_MODE, GL_LINEAR);
break;
}
float fFogColor[] = { Config->cFogColor.R, Config->cFogColor.G, Config->cFogColor.B, Config->cFogColor.A };
glFogfv(GL_FOG_COLOR, (float*)&fFogColor);
glFogf(GL_FOG_DENSITY, Config->fFogDensity);
glFogf(GL_FOG_START, Config->fFogStart);
glFogf(GL_FOG_END, Config->fFogEnd);
BuildFont(S"Courier New");
wglMakeCurrent(0, 0);
return true;
}
void CEngine::Destroy()
{
MakeCurrent();
DestroyFont();
MakeNotCurrent();
DestroyTextures();
ReleaseDC(hWND, hDC);
wglDeleteContext(hGLRC);
}
void CEngine::MakeCurrent()
{
wglMakeCurrent(hDC, hGLRC);
}
void CEngine::MakeNotCurrent()
{
wglMakeCurrent(0, 0);
}
void CEngine::BuildFont(String *FontName)
{
HFONT Font;
HFONT OldFont;
void *pFontName = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(FontName).ToPointer();
iFontBase = glGenLists(96);
Font = CreateFont(-12, // Height
0, // Width
0, // Angle
0, // Escape angle
FW_BOLD, // Font weight
false, // Italic
false, // Underline
false, // Strikeout
ANSI_CHARSET, // Character Set Identifier
OUT_TT_PRECIS, // Output Precision
CLIP_DEFAULT_PRECIS, // Clipping Precision
ANTIALIASED_QUALITY, // Output Quality
FF_DONTCARE | DEFAULT_PITCH, // Family And Pitch
(LPCSTR)pFontName); // Font Name
OldFont = (HFONT)SelectObject(hDC, Font);
wglUseFontBitmaps(hDC, 32, 96, iFontBase);
SelectObject(hDC, OldFont);
DeleteObject(Font);
System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr(pFontName)));
}
void CEngine::DestroyFont()
{
glDeleteLists(iFontBase, 96);
}
void CEngine::Resize(int iWidth, int iHeight)
{
if(iWidth == 0 || iHeight == 0)
return;
MakeCurrent();
RECT rv;
GetClientRect(hWND, &rv);
Frustum->SetAspect((float)(rv.right - rv.left) / (float)(rv.bottom - rv.top));
Frustum->SetWidth((float)(rv.right - rv.left));
Frustum->SetHeight((float)(rv.bottom - rv.top));
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(Config->fFrustumFieldOfView, Frustum->GetAspect(), Config->fFrustumZNear, Config->fFrustumZFar);
glViewport(rv.left, rv.top, rv.right - rv.left, rv.bottom - rv.top);
glMatrixMode(GL_MODELVIEW);
MakeNotCurrent();
}
void CEngine::Paint()
{
if(World == NULL)
return;
MakeCurrent();
StartScene();
SetCamera();
DrawScene();
Start2D();
DrawInfo();
End2D();
EndScene();
MakeNotCurrent();
}
void CEngine::LoadTextures()
{
String *sWADString;
if(World->GetWADString(&sWADString) == false)
{
txtConsole->Print("WAD string not found.\n", Color::Red);
return;
}
MakeCurrent();
TextureManager->LoadTextures(sWADString);
MakeNotCurrent();
}
void CEngine::UpdateTextureFilter()
{
if(TextureManager == NULL)
return;
MakeCurrent();
TextureManager->UpdateTextureFilter();
MakeNotCurrent();
}
void CEngine::DestroyTextures()
{
if(TextureManager == NULL)
return;
MakeCurrent();
TextureManager->DestroyTextures();
MakeNotCurrent();
}
void CEngine::PreRenderLoop()
{
Camera->InitializePerformanceCounter();
}
void CEngine::EnterRenderLoop()
{
bRender = true;
PreRenderLoop();
do
{
Application::DoEvents();
if(System::Windows::Forms::Form::ActiveForm == NULL)
{
System::Threading::Thread::Sleep(100);
continue;
}
MakeCurrent();
StartScene();
MoveCamera();
SetCamera();
CullScene();
DrawScene();
Start2D();
DrawInfo();
End2D();
EndScene();
MakeNotCurrent();
}
while(bRender == true);
}
void CEngine::ExitRenderLoop()
{
bRender = false;
}
void CEngine::SetWorld(CWorld *World, CTextureManager *TextureManager)
{
World->UpdateBrushCount();
txtConsole->Print(String::Concat(World->GetBrushCount().ToString(), S" brushes loaded.\n"), Color::Green);
this->World = World;
this->HighlightObject = NULL;
this->PointFile = NULL;
DestroyTextures();
this->TextureManager = TextureManager;
LoadTextures();
World->UpdateColors();
txtConsole->Print("Calculating texture coordinates.\n", Color::Gray);
World->UpdateTexCoords(TextureManager);
txtConsole->Print("Calculating bounding boxes.\n", Color::Gray);
World->UpdateBoundingBoxes();
this->Camera->Reset();
bMousePressed = false;
bW = false;
bA = false;
bS = false;
bD = false;
bShift = false;
bUp = false;
bDown = false;
bRight = false;
bLeft = false;
}
CTextureManager *CEngine::GetTextureManager()
{
return this->TextureManager;
}
void CEngine::SetHighlightObject(CWorldObject *HighlightObject)
{
this->HighlightObject = HighlightObject;
}
void CEngine::SetPointFile(CPointFile *PointFile)
{
this->PointFile = PointFile;
}
void CEngine::SetMousePosition(int X, int Y)
{
vMouseNew.X = X;
vMouseNew.Y = Y;
}
void CEngine::SetMousePressed(bool bMousePressed)
{
this->bMousePressed = bMousePressed;
}
void CEngine::SetKeyPressed(System::Windows::Forms::Keys Key, bool bKeyPressed)
{
switch(Key)
{
case System::Windows::Forms::Keys::W:
bW = bKeyPressed;
break;
case System::Windows::Forms::Keys::A:
bA = bKeyPressed;
break;
case System::Windows::Forms::Keys::S:
bS = bKeyPressed;
break;
case System::Windows::Forms::Keys::D:
bD = bKeyPressed;
break;
case System::Windows::Forms::Keys::Up:
bUp = bKeyPressed;
break;
case System::Windows::Forms::Keys::Down:
bDown = bKeyPressed;
break;
case System::Windows::Forms::Keys::Right:
bRight = bKeyPressed;
break;
case System::Windows::Forms::Keys::Left:
bLeft = bKeyPressed;
break;
case System::Windows::Forms::Keys::ShiftKey:
bShift = bKeyPressed;
break;
}
}
void CEngine::ClearBuffers()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
void CEngine::MoveCamera()
{
Vertex2i vMovement;
Camera->UpdateTimeElapsed();
vMovement.X = vMouseOld.X - vMouseNew.X;
vMovement.Y = vMouseOld.Y - vMouseNew.Y;
if(bMousePressed)
{
Camera->MoveCameraAngles(Config->bInvertCamera ? -vMovement.Y : vMovement.Y, vMovement.X);
}
vMouseOld.X = vMouseNew.X;
vMouseOld.Y = vMouseNew.Y;
float fWalk = 0.0f, fStrafe = 0.0f;
if(bW || bUp)
{
fWalk += Config->fCameraSpeed;
}
if(bS || bDown)
{
fWalk -= Config->fCameraSpeed;
}
if(bD || bRight)
{
fStrafe -= Config->fCameraSpeed;
}
if(bA || bLeft)
{
fStrafe += Config->fCameraSpeed;
}
if(bShift)
{
fWalk *= Config->fCameraBoost;
fStrafe *= Config->fCameraBoost;
}
Camera->MoveCamera(fWalk, fStrafe);
}
void CEngine::SetCamera()
{
Camera->SetCamera();
}
void CEngine::CullScene()
{
Frustum->ResetCulled();
Frustum->CalculateFrustum();
World->CullWorld(Frustum);
}
void CEngine::StartScene()
{
ClearBuffers();
}
void CEngine::DrawScene()
{
switch(Config->eRenderMode)
{
case RenderMode::Textured:
World->DrawWorldTextured();
break;
case RenderMode::Solid:
World->DrawWorldSolid();
break;
case RenderMode::WireFrame:
World->DrawWorldWireFrame();
break;
case RenderMode::Points:
World->DrawWorldPoints();
break;
}
if(Config->bOutlineScene)
World->Outline();
if(Config->bDrawSelection && this->HighlightObject != NULL)
HighlightObject->Highlight(false);
if(this->PointFile != NULL)
PointFile->DrawPoints();
}
void CEngine::EndScene()
{
RenderToScreen();
}
void CEngine::Start2D()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0.0f, Frustum->GetWidth(), 0.0f, Frustum->GetHeight());
glScalef(1.0f, -1.0f, 1.0f);
glTranslatef(0.0f, -Frustum->GetHeight(), 0.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
//glNormal3f(0.0f, 0.0f, 1.0f);
}
void CEngine::DrawInfo()
{
Color3uc Color;
Color.R = 255;
Color.G = 0;
Color.B = 0;
RenderText(String::Concat(S"FPS: ", Camera->GetFPS().ToString("0.00")), 4, 4, Color);
RenderText(String::Concat(S"Brushes drawn: ", (World->GetBrushCount() - Frustum->GetCulled()).ToString(), S"/", World->GetBrushCount().ToString()), 4, 16, Color);
}
void CEngine::RenderText(String *Text, int X, int Y, Color3uc Color)
{
void *pText = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(Text).ToPointer();
glColor3ub(Color.R, Color.G, Color.B);
glRasterPos2i(X, Y + 8);
glPushAttrib(GL_LIST_BIT);
glListBase(iFontBase - 32);
glCallLists(Text->Length, GL_UNSIGNED_BYTE, pText);
glPopAttrib();
glRasterPos2i(0, 0);
System::Runtime::InteropServices::Marshal::FreeHGlobal((IntPtr(pText)));
}
void CEngine::End2D()
{
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void CEngine::RenderToScreen()
{
glFlush();
SwapBuffers(hDC);
}
bool CEngine::TestExtension(String *sExtension)
{
MakeCurrent();
char *szExtension = (char *)(System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(sExtension)).ToPointer();
char *p = (char *)glGetString(GL_EXTENSIONS);
char *end;
int extNameLen;
extNameLen = strlen(szExtension);
end = p + strlen(p);
while(p < end)
{
int n = strcspn(p, " ");
if ((extNameLen == n) && (strncmp(szExtension, p, n) == 0))
{
System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)szExtension));
MakeNotCurrent();
return true;
}
p += (n + 1);
}
System::Runtime::InteropServices::Marshal::FreeHGlobal(IntPtr((void*)szExtension));
MakeNotCurrent();
txtConsole->Print(String::Concat("Extension ", sExtension, " not supported.\n"), Color::Red);
return false;
}